package com.xie.authority_system.controller;

import com.xie.authority_system.config.redis.RedisService;
import com.xie.authority_system.entity.Permission;
import com.xie.authority_system.entity.User;
import com.xie.authority_system.entity.UserInfo;
import com.xie.authority_system.utils.JwtUtils;
import com.xie.authority_system.utils.MenuTree;
import com.xie.authority_system.utils.Result;
import com.xie.authority_system.vo.RouterVo;
import com.xie.authority_system.vo.TokenVo;
import io.jsonwebtoken.Jwts;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author 谢金成
 * @date 2024/1/16 16:47
 */
@RestController
@RequestMapping("/api/sysUser")
public class SysUserController {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisService redisService;

    /**
     * 刷新token
     *
     * @param request
     * @return
     */
    @PostMapping("/refreshToken")
    public Result<TokenVo> refreshToken(HttpServletRequest request) {
        // 获取token
        String token = request.getHeader("token");
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }

        // 从Spring security上下文中获取用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails userDetails = (UserDetails) authentication.getPrincipal();
        // 生成新的token
        String newToken = "";
        // 验证提交过来的token信息是否是合法的
        if (jwtUtils.validateToken(token, userDetails)) {
            newToken = jwtUtils.refreshToken(token);
        }

        // 获取本次token的到期时间
        long expireTime = Jwts.parser()
                .verifyWith(jwtUtils.getKey())
                .build()
                .parseSignedClaims(newToken.replace("jwt_", ""))
                .getPayload()
                .getExpiration()
                .getTime();

        // 清除原来的token信息
        String oldTokenkey = "token_" + token;
        redisService.del(oldTokenkey);

        // 将新的token信息保存在缓存中
        String tokenKey = "token_" + newToken;
        redisService.set(tokenKey, newToken, jwtUtils.getExpiration() / 1000);

        // 创建tokenVo对象
        TokenVo tokenVo = new TokenVo(expireTime, newToken);
        // 返回数据
        return Result.ok(tokenVo).message("token刷新成功");
    }


    @GetMapping("/getInfo")
    public Result getInfo() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (ObjectUtils.isEmpty(authentication)) {
            return Result.error().message("用户信息查询失败");
        }

        // 获取用户信息
        User user = (User) authentication.getPrincipal();

        // 获取该用户权限信息
        List<Permission> permissionList = user.getPermissionList();

        // 获取权限编码
        Object[] roles = permissionList.stream()
                .filter(Objects::nonNull)
                .map(Permission::getCode)
                .filter(Objects::nonNull)
                .toArray();

        // 创建用户信息
        UserInfo userInfo = new UserInfo(user.getId(), user.getUsername(), user.getAvatar(), null, roles);

        // 返回数据
        return Result.ok(userInfo).message("用户信息查询成功");
    }

    @GetMapping("/getMenuList")
    public Result getMenuList() {
        // 从Spring security上下文中拿到用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User user = (User) authentication.getPrincipal();
        // 获取该用户的权限列表
        List<Permission> permissionList = user.getPermissionList();
        // 筛选当前用户拥有的菜单类型
        List<Permission> collect = permissionList.stream()
                .filter(item -> item != null && item.getType() != 2)
                .collect(Collectors.toList());

        // 生成路由信息
        List<RouterVo> routerVoList = MenuTree.makeRouter(collect, 0L);
        // 返回数据
        return Result.ok(routerVoList).message("菜单数据获取成功");
    }

    @PostMapping("/logout")
    public Result logout(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("token");
        if (ObjectUtils.isEmpty(token)) {
            token = request.getParameter("token");
        }

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            new SecurityContextLogoutHandler().logout(request, response, authentication);
            redisService.del("token_" + token);
            return Result.ok().message("用户退出成功");
        }

        return Result.error().message("用户退出失败");
    }
}
